// 1.1 JWT
// 生成JWT
use p256::ecdsa::SigningKey;
use p256::ecdsa::VerifyingKey;
use once_cell::sync::Lazy;
use base64::engine::general_purpose::URL_SAFE;
use base64::Engine;
use rand::rngs::OsRng;
use crate::runtime::GLOBAL_RUNTIME;
use anyhow::{Result, anyhow};
use crate::db::{db_insert::db_insert, db_select::db_select};

#[derive(Debug)]
pub struct Jwt{
    pub signing_key: SigningKey,
    pub verify_key: VerifyingKey,
    pub kty: String,
    pub x_b64: String,
    pub y_b64: String,
    pub crv: String,
    pub d_b64: String,
}

use once_cell::sync::OnceCell;
pub static JWT_INSTANCE: OnceCell<Jwt> = OnceCell::new();
pub async fn jwt_init() {
    let jwt = load_or_generate_jwt().await.unwrap();
    JWT_INSTANCE.set(jwt).unwrap();
}
/// 尝试从数据库加载 JWT，如果不存在则生成新的并保存
async fn load_or_generate_jwt() -> Result<Jwt> {
    if let Ok(d_b64) = db_select("jwt_d").await {
        let d_bytes_vec = URL_SAFE.decode(&d_b64.value)?;
        // 尝试将 Vec<u8> 转换为 [u8; 32]
        let d_bytes: [u8; 32] = d_bytes_vec.try_into()
            .map_err(|_| anyhow!("Invalid private key length"))?;
        let signing_key = SigningKey::from_bytes(&d_bytes.into())?;
        let verify_key = signing_key.verifying_key().clone();

        let encoded_point = verify_key.to_encoded_point(false);
        let x_b64 = URL_SAFE.encode(encoded_point.x().unwrap());
        let y_b64 = URL_SAFE.encode(encoded_point.y().unwrap());

        return Ok(Jwt {
            signing_key,
            verify_key,
            kty: "EC".to_string(),
            x_b64,
            y_b64,
            crv: "P-256".to_string(),
            d_b64: d_b64.value,
        });
    }

    // 如果数据库中没有，则生成新的
    let signing_key = SigningKey::random(&mut OsRng);
    let verify_key = signing_key.verifying_key().clone();
    let encoded_point = verify_key.to_encoded_point(false);

    let x_b64 = URL_SAFE.encode(encoded_point.x().unwrap());
    let y_b64 = URL_SAFE.encode(encoded_point.y().unwrap());
    let d_b64 = URL_SAFE.encode(signing_key.to_bytes());

    // 写入数据库
    db_insert("jwt_d", &d_b64).await?;
    db_insert("jwt_x", &x_b64).await?;
    db_insert("jwt_y", &y_b64).await?;
    db_insert("jwt_kty", "EC").await?;
    db_insert("jwt_crv", "P-256").await?;

    // println!("{d_b64}");
    Ok(Jwt {
        signing_key,
        verify_key,
        kty: "EC".to_string(),
        x_b64,
        y_b64,
        crv: "P-256".to_string(),
        d_b64,
    })
}